II Something
by Clark Hugh Stiles
November 21, 2001 

Analysis Revised -- Last week's routine really, really didn't work right. This new one does however. I dumped the non-6502 instructions (PHX and PLX do work on the GS, but the routine itself is a bust anyway), a mistake I'd not realized until I was looking up something else. These mostly relocatable routines will do specific tasks needed by the finished program. The first one does the actual processing of the data obtained by the ONLINE call to be shown next time. Note that this is assembly code, and after the line beginning with 1000 there's a space ahead of the rest of the line until [return]. 

Program Listing: 
CALL -151
!
1000:LDX #$EF
LDA #$00
STA 1E00,X
INX
BNE 1004
CLC
TAY
TAX
LDA 1F00,X
AND #$0F
BEQ 1021
LDA 1F00,X
AND #$F0
STA 1EF0,Y
INY
CPY #$10
BEQ 1027
CLC
TXA
ADC #$10
BCC 100C
STY 1EEF
RTS
[return]
*BSAVE ROUTE1000,A$1000,L$2B [control-C,return] 
End of Program Listing. 

This routine assumes that the ONLINE call will use the memory page at $1F00 for its buffer; that the sixteen bytes at $1EF0 will be used to store the unit codes processed out of the first buffer; and that byte $1EEF will be used to store the count of the valid unit codes (unit codes are used by the READ_and WRITE_BLOCK calls). 

The program begins with Load X register with #$EF, then Loads A (the Accumulator) with zero. The rest of the code down to BNE 1004 just zeroes out the latter two buffers. STA 1E00,X means to store the contents of A (in this case the zero we loaded) at $1E00 plus the value of X. INX increments (adds one) to X, and BNE loops the flow of the program until X gets to zero (these 8 bit registers and the 8 bit Accumulator never exceed 255). 

CLC clears the carry, which got set when X "wrapped around" from 255 to zero. A still holds a zero, so we TAY and TAX (transfer A to X and Y respectively) to prepare the way for the main purpose -- analyzing, processing, and storing the unit codes. A, X, and Y all contain zero at this point. 

LDA 1F00,X loads A with the value in memory location $1F00 plus X. 

AND #$0F forces zeroes into bits 7 through 4, in order to figure out whether the rest of byte at $1F00 plus X contains a valid entry. Valid entries have non-zero contents in bits 3 through 0. BEQ (Branch on Equal) 1021 means "flow to memory location $1021 if the value is zero". 

If the entry is valid, we fall through the BEQ and reload A with $1F00 plus X. Then we AND #$F0 to force zeroes in bits 3 through 0 (because that's what the _READ and _WRITE calls expect) and store the result in $1EF0 plus Y. Y is then incremented with an INY, and if found to be equal to 16 (#$10) routes the program to the exit. 

If we fall through the BEQ, we again CLC to prepare for addition, transfer X to the Accumulator, add 16, and if the Carry bit is clear, branch the program to the TAX, to put the properly incremented value back into X, and repeat the process. This means that we grab the first byte of memory page $1F, 

Eventually we get to the end of that memory page by reading byte $1FF0 (add sixteen, get $00 as the Accumulator value "wraps around"), processing it as usual, and storing it if necessary. The check on Y to see if it equals 16 just speeds the program and provides a failsafe in case I screwed up again. 

The exit of this routine stores the value of Y at $1EEF. That's because Y contains the count of valid unit numbers which will be used by the interface for the program. 

The next routine (also written at $1000) is the new and improved versions of ONLINE and READ_and WRITE_BLOCK calls. They contain the proper JSR and JMP to evaluate any MLI (Machine Language Interface) errors, which they share to save space. They have their parameter tables hard coded (that's a requirement, although since it's a vector it's considered permissible to alter the values in order to avoid the charge of "self-modifying code") to point to $1EEB (four bytes) and $1EE5 (six bytes), which will reside at the end of the memory space of the finished program. 

Program Listing: 
CALL -151
!
1000:LDA #00
TAX
STA 1F00,X
INX
BNE 1003
JSR BF00
NOP
NOP
NOP
BCC 101F
JSR BE8B
JMP BE09
LDA #00
TAX
STA 2000,X
INX
BNE 101A
STA 2100,X
INX
BNE 1020
JSR BF00
NOP
NOP
NOP
BCS 1011
RTS
[return]
*100C:C5 EB 1E
*1029: 80 E5 1E
*BSAVE ONLINE.RD.BLOCK,A$1000,L$2C [control-C,return] 
End of Program Listing. 

Since this uses the Miniassembler, I plugged in three consecutive NOP (No Operand) operations where the MLI data goes, and then typed it in near the end, just before the BSAVE. After you enter all of it, try 1000L to see what happened. 

Our MLI call to ONLINE will use $1F00.1FFF to store the information on all online volumes. To keep it neat and tidy, the first thing we need to do is zero out that memory page, using the same method seen in the analysis routine above. READ_ and WRITE_BLOCK uses $2000.21FF and so it likewise zeroes out that buffer space before making the call. 

The entry point for READ_ is $1017, but that won't be the case in the finished program because these are relocatable routines. I'll show you how to build them into a single program with BLOADs. It's a little time consuming, but it works well enough, and after the final BSAVE will no longer be necessary. In a full Assembler package all this is automated. 

The above JSR BE8B converts the MLI error (if any) to a value recognizable to BASIC, and the JMP BE09 heads for the error handling routine. BASIC has the ONERR instruction which can be used to intercept and handle errors. By the time this program is completed, it may have something similar, or may just not worry about it, having been designed with a devil may care attitude. You didn't actually NEED anything on those disks you're zapping, did you? 

II Infinitum! 